#include "spi_driver.h"

QueueHandle_t spi_queue_handle;
QueueHandle_t spi2_queue_handle;

static TaskHandle_t spi_handle;
static TaskHandle_t spi2_handle;

spi_device_handle_t spi;
spi_device_handle_t spi2;
static uint8_t data[2000];

/*spi初始化*/
void spi_init(u8 port,spi_host_device_t spi_host,spi_common_dma_t SPI_DMA,spi_device_handle_t *spi)
{
    esp_err_t ret;
    spi_bus_config_t buscfg={
        .miso_io_num=-1,
        .mosi_io_num=port,
        .sclk_io_num=-1,
        .quadwp_io_num=-1,
        .quadhd_io_num=-1,
        .max_transfer_sz=10000
    };

    spi_device_interface_config_t devcfg={
        .clock_speed_hz=4*1000*1000,           //Clock out at 8 MHz
        .mode=0,                                //SPI mode 0
        .spics_io_num=-1,               //CS pin
        .queue_size=7,                          //We want to be able to queue 7 transactions at a time

    };

    ret=spi_bus_initialize(spi_host, &buscfg, SPI_DMA);
    ESP_ERROR_CHECK(ret);

    ret=spi_bus_add_device(spi_host, &devcfg, spi);
    ESP_ERROR_CHECK(ret);
}

/*SPI发送函数*/
void send_data(const uint8_t *data, int len,spi_device_handle_t spi)
{
    esp_err_t ret;
    spi_transaction_t t;
    if (len==0) return;             //no need to send anything
    memset(&t, 0, sizeof(t));       //Zero out the transaction
    t.length=len*8;                 //Len is in bytes, transaction length is in bits.
    t.tx_buffer=data;               //Data
    t.user=(void*)1;                //D/C needs to be set to 1
    ret=spi_device_polling_transmit(spi, &t);  //Transmit!
    assert(ret==ESP_OK);            //Should have had no issues.
}


/*spi总线释放函数*/
void spi_close(spi_device_handle_t spi,spi_host_device_t spi_host,spi_common_dma_t SPI_DMA)
{
    esp_err_t ret;
    ret = spi_bus_remove_device(spi);
    ESP_ERROR_CHECK(ret);
    ret = spi_bus_free(spi_host);
    ESP_ERROR_CHECK(ret);
}


void spi_task()
{
    LOG_INFO("disp_task : enter disp_loop()\n");
    spi_queue_handle = xQueueCreate(10,sizeof(spi_send_param *));

    spi_send_param *spi_send_buffer = NULL;
    while(1)
    {
        memset(data,0,2000); //数组清零
        data[0]=0XFF;
        if(xQueueReceive(spi_queue_handle,&spi_send_buffer,portMAX_DELAY))
        {
           if (spi_send_buffer != NULL)
           {
                for(int i = 0 ; i<spi_send_buffer->send_len; i+=4) //4个字节代表一个灯珠
                {
                    for(int j = 0 ; j<4; j++) //重组32位
                    {
                        uint8_t cr = spi_send_buffer->send_data[i+j]; //RGB位取色
                        uint8_t mask = 0x80;
                        uint8_t low=0;
                        uint8_t high=0;
                        for(int k = 0; k<4; k++)
                        {
                            high = (mask&cr)?TH:TL;
                            mask>>=1;
                            low = (mask&cr)?TH:TL;
                            mask>>=1;
                            data[1+(i+j)*4+k]=(((high<<4)&0xF0)|(low&0x0F));
                        }
                    }   
                }
                send_data(data,(spi_send_buffer->send_len*4+1),spi); //按灯组发送
                vPortFree(spi_send_buffer->send_data);
                vPortFree(spi_send_buffer);
           }
           else
           {
                LOG_ERROR("queue receive err\n");
           }
            spi_send_buffer = NULL;
        }
        
    }
}

void spi2_task()
{
    LOG_INFO("disp_task : enter spi2_task()\n");
    spi2_queue_handle = xQueueCreate(10,sizeof(u8 *));
    u8 *spi2_data =NULL;
    u8 data1[50];
    while(1)
    {
        memset(data1,0,12*4+1); //数组清零
        data1[0]=0XFF;
        if(xQueueReceive(spi2_queue_handle,&spi2_data,portMAX_DELAY))
        {
            if (spi2_data != NULL)
            {    
                for(int i = 0 ; i<12; i+=4) //4个字节代表一个灯珠
                {
                    for(int j = 0 ; j<4; j++) //重组32位
                    {
                        uint8_t cr = spi2_data[i+j]; //RGB位取色
                        uint8_t mask = 0x80;
                        uint8_t low=0;
                        uint8_t high=0;
                        for(int k = 0; k<4; k++)
                        {
                            high = (mask&cr)?TH:TL;
                            mask>>=1;
                            low = (mask&cr)?TH:TL;
                            mask>>=1;
                            data1[1+(i+j)*4+k]=(((high<<4)&0xF0)|(low&0x0F));
                        }
                    }   
                }
                send_data(data1,(12*4+1),spi2); //按灯组发送
                vPortFree(spi2_data);
                spi2_data =NULL;
           }

        }
    }
}






void device_spi_init(void)
{
    printf("device_spi_int():enter\n"); 
    spi_init(PIN_NUM_MOSI1,HSPI_HOST2,SPI_DMA_CH1,&spi);
    xTaskCreate(spi_task, "spi_task", 4096, NULL, TASK_PROP_DISPLAY, &spi_handle);
}


void device_spi2_init(void)
{
    printf("device_spi2_int():enter");
    spi_init(PIN_NUM_MOSI2,HSPI_HOST3,SPI_DMA_CH2,&spi2);
    xTaskCreate(spi2_task, "spi2_task", 3072, NULL, TASK_PROP_DISPLAY, &spi2_handle);
}
